﻿#include "CVlcOper.h"
#include <QCoreApplication>
#include <QtConcurrent/QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QEventLoop>
#include <QTimer>

// 全局静态变量
static libvlc_instance_t* g_instance = nullptr;

bool CVlcOper::stopVlcPlayerSafe(libvlc_media_player_t* player, int timeoutMs)
{
	if (!player) return false;


	libvlc_event_attach(libvlc_media_player_event_manager(player),libvlc_MediaPlayerStopped,&CVlcOper::onVlcStopped,this);
	// 异步停止操作
	QFuture<void> future = QtConcurrent::run([player]() {
		try
		{
			libvlc_media_player_stop(player); // 可能阻塞

		}
		catch (const std::exception& e) {
			qWarning() << "[stopVlcPlayerSafe] 捕获异常:" << e.what();
		}
		catch (...) {
			qWarning() << "[stopVlcPlayerSafe] 捕获未知异常";
		}
		});
	// 监控 future
	QFutureWatcher<void> watcher;
	watcher.setFuture(future);

	// 创建事件循环，等待完成或超时
	QEventLoop loop;
	QObject::connect(&watcher, &QFutureWatcher<void>::finished, &loop, &QEventLoop::quit);

	QTimer timer;
	timer.setSingleShot(true);
	QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);

	timer.start(timeoutMs);
	loop.exec(); // 等待子线程完成或超时
	if (!future.isFinished())
	{
		return false;
	}
	else
	{
		return true;
	}
}

void CVlcOper::onVlcStopped(const libvlc_event_t*, void* opaque)
{
	auto* selfRaw = static_cast<CVlcOper*>(opaque);
	QPointer<CVlcOper> self = selfRaw;
	if (!self)
	{
		return ;
	}
	self->m_bStopped = true;
}




CVlcOper::CVlcOper(CDevDataCam* pDevDataCam, const QString& url)
{
	m_sUrl = url;
	m_nWidth = 640;
	m_nHeight = 640;
	m_bInit = false;
	m_bVideoRun = false;
	m_bStopped = false;
	m_pMedia = nullptr;
	m_pMediaPlayer = nullptr;
	init();
}

CVlcOper::~CVlcOper()
{
	if (m_pMediaPlayer == NULL)
	{
		return;
	}

	if (m_pMedia != NULL)
	{
		libvlc_media_release(m_pMedia);
		m_pMedia = NULL;
	}
	if (m_pMediaPlayer != NULL)
	{
		libvlc_media_player_release(m_pMediaPlayer);
		m_pMediaPlayer = NULL;
	}
	m_cImageLock.tryLock(50);
	{
		if (m_pCurrentFrame != NULL)
		{
			delete m_pCurrentFrame;
			m_pCurrentFrame = NULL;
		}
		m_cImageLock.unlock();
	}
}

void CVlcOper::setImageWidget(QWidget* pWidget)
{
	QLabel* label = qobject_cast<QLabel*>(pWidget);
	m_pImageLabel = QPointer<QLabel>(label);
	m_nWidth = m_pImageLabel->width();
	m_nHeight = m_pImageLabel->height();
	m_pCurrentFrame = new QImage(m_pImageLabel->width(), m_pImageLabel->height(), QImage::Format_RGB32);
	m_cImageLock.lock();
	libvlc_video_set_format(m_pMediaPlayer, "RV32", m_pCurrentFrame->width(), m_pCurrentFrame->height(), m_pCurrentFrame->bytesPerLine());
	m_cImageLock.unlock();
}


bool CVlcOper::init()
{
	if (m_bInit)
	{
		return true;
	}
	// 初始化 VLC 实例
	if (!g_instance)
	{

		// 传入 VLC 参数
		const char* args[] = { "--intf=dummy", "--no-xlib", "--no-video-title-show" };
		int argc = sizeof(args) / sizeof(args[0]);
		g_instance = libvlc_new(argc, args);
	}
	m_pVlcInstance = g_instance;
	// 创建媒体
	m_pMedia = libvlc_media_new_location(m_pVlcInstance, m_sUrl.toStdString().c_str());
	if (!m_pMedia)
	{
		return false;
	}
	// 创建媒体播放器
	m_pMediaPlayer = libvlc_media_player_new_from_media(m_pMedia);
	if (!m_pMediaPlayer)
	{
		return false;
	}
	// 设置回调
	libvlc_video_set_callbacks(m_pMediaPlayer, lockCallback, unlockCallback, displayCallback, this);
	m_bInit = true;
	return true;
}


bool CVlcOper::startCapture()
{
	if (!m_bInit)
	{
		return false;
	}
	if (m_pMediaPlayer == nullptr)
	{
		return false;
	}
	if (libvlc_media_player_play(m_pMediaPlayer) != 0)
	{
		return false;
	}
	m_bVideoRun = true;
	m_bStopped = false;
	return true;
}

bool CVlcOper::stopCapture()
{
	if (m_pMediaPlayer == nullptr)
	{
		m_bVideoRun = false;
		return false;
	}
	libvlc_media_player_set_pause(m_pMediaPlayer, 1);
	m_bVideoRun = false;
	QThread::msleep(100);
	if (!stopVlcPlayerSafe(m_pMediaPlayer, 2000))
	{
		m_pMediaPlayer = nullptr;
		return false;
	}
	else
	{
		if (waitTime(1000, m_bStopped))
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}


void* CVlcOper::lockCallback(void* opaque, void** planes)
{
	auto* selfRaw = static_cast<CVlcOper*>(opaque);
	QPointer<CVlcOper> self = selfRaw;
	if (!self)
	{
		*planes = nullptr;
		return nullptr;
	}
	self->m_cImageLock.lock();
	if (self->m_pCurrentFrame != nullptr)
	{
		*planes = self->m_pCurrentFrame->bits();
	}
	return nullptr;
}

void CVlcOper::unlockCallback(void* opaque, void* picture, void* const* planes)
{
	auto* selfRaw = static_cast<CVlcOper*>(opaque);
	QPointer<CVlcOper> self = selfRaw;
	if (!self)
	{
		return;
	}
	Q_UNUSED(opaque);
	Q_UNUSED(picture);
	Q_UNUSED(planes);
	self->m_cImageLock.unlock();
}


void CVlcOper::displayCallback(void* opaque, void* picture)
{
	Q_UNUSED(picture);
	auto* selfRaw = static_cast<CVlcOper*>(opaque);
	QPointer<CVlcOper> self = selfRaw;
	if (!self || !self->m_pImageLabel || !self->m_pCurrentFrame)
		return;
	if (!self->m_bVideoRun)
	{
		return;
	}
	// 使用 QPointer 捕获，防止对象已被释放


	QMetaObject::invokeMethod(QCoreApplication::instance(), [self]() {
		if (!self)
			return; // 对象已被释放，直接返回
		if (!self->m_bVideoRun)
		{
			return;
		}
		if (self->m_pImageLabel && self->m_pCurrentFrame) {
			QImage frameCopy;
			self->m_cImageLock.tryLock(50);
			{
				frameCopy = self->m_pCurrentFrame->copy(); // 拷贝当前帧
				self->m_cImageLock.unlock();
				self->m_pImageLabel->setPixmap(QPixmap::fromImage(frameCopy));
			}

		}
		}, Qt::QueuedConnection);
}


bool CVlcOper::waitTime(int nMs, bool& bRun)
{
	bool bOk = true;
	int nCount = nMs / 5;
	int nIndex = 0;
	while (!bRun)
	{
		QEventLoop loop;
		QTimer::singleShot(5, &loop, SLOT(quit()));
		loop.exec();
		if (nIndex > nCount)
		{
			bOk = false;
			break;
		}
		nIndex++;
	}
	return bOk;
}